﻿using System;
using System.Collections.Generic;
using NHibernate;
using NHibernate.Criterion;
using Neturion.Dados;
using Neturion.IRepositorios;

namespace Neturion.Repositorios
{
    public class RepositorioCliente : IRepositorioCliente
    {
        public Cliente Inserir(Cliente cliente)
        {
            cliente.InicioVigenciaCliente = cliente.InicioVigenciaCliente.HasValue
                                                  ? cliente.InicioVigenciaCliente.Value.Date
                                                  : cliente.InicioVigenciaCliente;
            cliente.FimVigenciaCliente = cliente.FimVigenciaCliente.HasValue
                                                   ? cliente.FimVigenciaCliente.Value.Date
                                                   : cliente.FimVigenciaCliente;

            GerenciadorBDConfigs.Instance.SessaoAtual().Save(cliente);
            return cliente;
        }

        public Cliente Atualizar(Cliente cliente)
        {
            Cliente tmpCliente = ObterPorId(cliente.ClienteId);
            // Atribuicao dos valores do objeto da memoria para o objeto obtido no banco de dados
            tmpCliente.Codigo = cliente.Codigo;
            tmpCliente.Pessoa = cliente.Pessoa;
            tmpCliente.DataCadastro = cliente.DataCadastro;
            tmpCliente.RamoAtividade = cliente.RamoAtividade;
            tmpCliente.InicioVigenciaCliente = cliente.InicioVigenciaCliente.HasValue
                                                   ? cliente.InicioVigenciaCliente.Value.Date
                                                   : cliente.InicioVigenciaCliente;
            tmpCliente.FimVigenciaCliente = cliente.FimVigenciaCliente.HasValue
                                                   ? cliente.FimVigenciaCliente.Value.Date
                                                   : cliente.FimVigenciaCliente;
            tmpCliente.ObservacaoCliente = cliente.ObservacaoCliente;
            tmpCliente.NeturionLog = cliente.NeturionLog;
            
            GerenciadorBDConfigs.Instance.SessaoAtual().Merge(tmpCliente);
            return tmpCliente;
        }

        public void Excluir(Cliente cliente)
        {
            GerenciadorBDConfigs.Instance.SessaoAtual().Delete(cliente);
        }

        public IList<Cliente> ObterTodos()
        {
            ICriteria criteria = GerenciadorBDConfigs.Instance.SessaoAtual().CreateCriteria(typeof(Cliente));
            return criteria.List<Cliente>() as List<Cliente>;
        }

        public IList<Cliente> ObterTodos(int inicio, int quantidade, int quantidadeMinima, string nomeRazaoSocial, string apelidoFantasia, string nomeReduzido, string cpfCnpj, Midia midia, EnumTipoPessoa enumTipoPessoa, RamoAtividade ramoAtividade, DateTime? dataNascimentoAberturaDe, DateTime? dataNascimentoAberturaAte, DateTime? cadastroDe, DateTime? cadastroAte, DateTime? inicioVigenciaDe, DateTime? inicioVigenciaAte, DateTime? fimVigenciaDe, DateTime? fimVigenciaAte)
        {
            if (quantidade.Equals(0))
            {
                quantidade = quantidadeMinima;
            }

            ICriteria criteria = GerenciadorBDConfigs.Instance.SessaoAtual().CreateCriteria(typeof(Cliente))
                .SetFirstResult(inicio).SetMaxResults(quantidade)
                .CreateAlias("Pessoa", "Pessoa");

            if (enumTipoPessoa.GetHashCode() != -1)
            {
                criteria.Add(Restrictions.Eq("Pessoa.EnumTipoPessoa", enumTipoPessoa));
            }

            if (!String.IsNullOrEmpty(nomeRazaoSocial))
            {

                criteria.Add(Restrictions.Like("Pessoa.NomeRazaoSocial", nomeRazaoSocial, MatchMode.Anywhere));
            }

            if (!String.IsNullOrEmpty(apelidoFantasia))
            {

                criteria.Add(Restrictions.Like("Pessoa.ApelidoFantasia", apelidoFantasia, MatchMode.Anywhere));
            }

            if (!String.IsNullOrEmpty(nomeReduzido))
            {
                criteria.Add(Restrictions.Like("Pessoa.NomeReduzido", nomeReduzido, MatchMode.Anywhere));
            }

            if (!String.IsNullOrEmpty(cpfCnpj))
            {
                criteria.Add(Restrictions.Eq("Pessoa.CpfCnpj", cpfCnpj));
            }

            if (midia != null)
            {
                criteria.Add(Restrictions.Eq("Pessoa.Midia", midia));
            }

            if (dataNascimentoAberturaDe.HasValue)
            {
                criteria.Add(dataNascimentoAberturaAte.HasValue
                    ? Restrictions.Between("Pessoa.DataNascimentoAbertura", dataNascimentoAberturaDe.Value.Date, dataNascimentoAberturaAte.Value.Date)
                    : Restrictions.Eq("Pessoa.DataNascimentoAbertura", dataNascimentoAberturaDe.Value.Date));
            }

            if (ramoAtividade != null)
            {
                criteria.Add(Restrictions.Eq("RamoAtividade", ramoAtividade));
            }
            
            if (cadastroDe.HasValue)
            {
                criteria.Add(cadastroAte.HasValue
                    ? Restrictions.Between("DataCadastro", cadastroDe.Value.Date, cadastroAte.Value.Date)
                    : Restrictions.Eq("DataCadastro", cadastroDe.Value.Date));
            }

            if (inicioVigenciaDe.HasValue)
            {
                criteria.Add(inicioVigenciaAte.HasValue
                    ? Restrictions.Between("InicioVigenciaCliente", inicioVigenciaDe.Value.Date, inicioVigenciaAte.Value.Date)
                    : Restrictions.Eq("InicioVigenciaCliente", inicioVigenciaDe.Value.Date));
            }

            if (fimVigenciaDe.HasValue)
            {
                criteria.Add(fimVigenciaAte.HasValue
                    ? Restrictions.Between("FimVigenciaCliente", fimVigenciaDe.Value.Date, fimVigenciaAte.Value.Date)
                    : Restrictions.Eq("FimVigenciaCliente", fimVigenciaDe.Value.Date));
            }

            return criteria.List<Cliente>() as List<Cliente>;
        }

        public Cliente ObterPorCpfCnpj(string cpfCnpj)
        {
            ICriteria criteria = GerenciadorBDConfigs.Instance.SessaoAtual().CreateCriteria(typeof(Cliente))
                .CreateAlias("Pessoa", "Pessoa")
                .Add(Restrictions.Eq("Pessoa.CpfCnpj", cpfCnpj));
            return criteria.UniqueResult<Cliente>();
        }

        public Cliente ObterPorPessoa(Pessoa pessoa)
        {
            ICriteria criteria = GerenciadorBDConfigs.Instance.SessaoAtual().CreateCriteria(typeof(Cliente))
                .Add(Restrictions.Eq("Pessoa", pessoa));
            return criteria.UniqueResult<Cliente>();
        }

        public Cliente ObterPorId(int id)
        {
            return GerenciadorBDConfigs.Instance.SessaoAtual().Get<Cliente>(id);
        }

        public IList<Cliente> ObterPorRamoAtividade(RamoAtividade ramoAtividade)
        {
            ICriteria criteria =
                GerenciadorBDConfigs.Instance.SessaoAtual().CreateCriteria(typeof (Cliente))
                    .Add(Restrictions.Eq("RamoAtividade", ramoAtividade));
            return criteria.List<Cliente>() as List<Cliente>;
        }

        public int ObterUltimoIdCodigoInteiro()
        {
            string[] literal = new string[] 
                {"a","b","c","d","e","f","g","h","i","j"
                ,"l","m","n","o","p","q","r","s","t","u","v","x","z","y"
                ,"w"};

            ICriteria criteria = GerenciadorBDConfigs.Instance.SessaoAtual().CreateCriteria(typeof(Cliente)).SetMaxResults(1);

            for (int i = 0; i <= literal.Length - 1; i++)
            {
                criteria.Add(Restrictions.Not(Restrictions.Like("Codigo", literal[i], MatchMode.Anywhere)));
            }

            criteria.AddOrder(Order.Desc("ClienteId"));


            Cliente cliente = criteria.UniqueResult<Cliente>();
            int ultimoCodigo = cliente != null ? cliente.ClienteId : 0;

            return ultimoCodigo;
        }

        public Cliente ObterPorCodigo(string codigo)
        {
            ICriteria criteria = GerenciadorBDConfigs.Instance.SessaoAtual().CreateCriteria(typeof(Cliente))
                .Add(Restrictions.Eq("Codigo", codigo));

            return criteria.UniqueResult<Cliente>() as Cliente;
        }
    }
}